/*
* 文件：WebSocketNative.cs
* 作者：王阳
* 时间：2022-11-11
* 描述：WebSocket网络客户端，WebGL平台
*/
using AOT;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace UnityX
{
    internal class WebSocketNative
    {
        private delegate void OpenCallback(int id);
        private delegate void MessageCallback(int id, IntPtr ptr);
        private delegate void ErrorCallback(int id, int code);
        private delegate void CloseCallback(int id);

#if UNITY_EDITOR || UNITY_WEBGL
        [DllImport("__Internal")]
        private static extern void WebSocketSetOpenCallback(OpenCallback callback);
        [DllImport("__Internal")]
        private static extern void WebSocketSetMessageCallback(MessageCallback callback);
        [DllImport("__Internal")]
        private static extern void WebSocketSetErrorCallback(ErrorCallback callback);
        [DllImport("__Internal")]
        private static extern void WebSocketSetCloseCallback(CloseCallback callback);

        [DllImport("__Internal")]
        internal static extern int WebSocketOpen(string url);
        [DllImport("__Internal")]
        internal static extern void WebSocketClose(int id);
        [DllImport("__Internal")]
        internal static extern int WebSocketSend(int id, byte[] buf, int size);
        [DllImport("__Internal")]
        internal static extern int WebSocketState(int id);
#else
        private static void WebSocketSetOpenCallback(OpenCallback callback) { }
        private static void WebSocketSetMessageCallback(MessageCallback callback) { }
        private static void WebSocketSetErrorCallback(ErrorCallback callback) { }
        private static void WebSocketSetCloseCallback(CloseCallback callback) { }

        internal static int WebSocketOpen(string url) { return 0; }
        internal static void WebSocketClose(int id) { }
        internal static int WebSocketSend(int id, byte[] buf, int size) { return 0; }
        internal static int WebSocketState(int id) { return 0; }
#endif

        private static Dictionary<int, WebSocketClient> sockets = new Dictionary<int, WebSocketClient>();

        static WebSocketNative()
        {
            WebSocketSetOpenCallback(OnOpenCallback);
            WebSocketSetMessageCallback(OnMessageCallback);
            WebSocketSetErrorCallback(OnErrorCallback);
            WebSocketSetCloseCallback(OnCloseCallback);
        }
        [MonoPInvokeCallback(typeof(OpenCallback))]
        private static void OnOpenCallback(int id)
        {
            if (sockets.TryGetValue(id, out var socket))
            {
                socket.OnOpen();
            }
        }
        [MonoPInvokeCallback(typeof(MessageCallback))]
        private static void OnMessageCallback(int id, IntPtr ptr)
        {
            if (sockets.TryGetValue(id, out var socket))
            {
                unsafe
                {
                    socket.OnMessage((byte*)ptr.ToPointer());
                }
            }
        }
        [MonoPInvokeCallback(typeof(ErrorCallback))]
        private static void OnErrorCallback(int id, int code)
        {
            if (sockets.TryGetValue(id, out var socket))
            {
                socket.OnError(code);
            }
        }
        [MonoPInvokeCallback(typeof(CloseCallback))]
        private static void OnCloseCallback(int id)
        {
            if (sockets.TryGetValue(id, out var socket))
            {
                socket.OnClose();
                sockets.Remove(id);
            }
        }

        internal static int AllocateInstance(string url, WebSocketClient webSocketClient)
        {
            int id = WebSocketOpen(url);
            sockets.Add(id, webSocketClient);
            return id;
        }
    }
}